// 2010年版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// TLS低电平连接和记录层

package tls

import (
	"bytes"
	"context"
	"crypto/cipher"
	"crypto/subtle"
	"crypto/x509"
	"errors"
	"fmt"
	"hash"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"
)

// Conn表示安全连接。
// 它实现了net.Conn接口。
type Conn struct {
	// 常数
	conn        net.Conn
	isClient    bool
	handshakeFn func(context.Context) error // （*Conn）.客户端握手或服务器握手

	// 如果连接当前正在传输，则握手状态为1
	// 应用程序数据（即，当前未处理握手）。
	// 此字段只能通过sync/atomic访问。
	handshakeStatus uint32
	// 握手后保持不变；由握手保护
	handshakeMutex sync.Mutex
	handshakeErr   error   // 握手导致的错误
	vers           uint16  // TLS版本
	haveVers       bool    // 版本已商定
	config         *Config // 传递给构造函数的配置
	// 握手统计在服务器上执行的握手次数
	// 到目前为止的联系。如果重新协商被禁用，则这是
	// 零或一。
	handshakes       int
	didResume        bool // 此连接是否为会话恢复
	cipherSuite      uint16
	ocspResponse     []byte   // 钉状OCSP反应
	scts             [][]byte // 来自服务器的签名证书时间戳
	peerCertificates []*x509.Certificate
	// verifiedChains包含我们构建的证书链，如下所示
	// 与服务器提供的相反。
	verifiedChains [][]*x509.Certificate
	// serverName包含客户端指示的服务器名称（如果有）。
	serverName string
	// 如果服务器回显安全协议，则安全重新协商为true
	// 重新谈判延期。（这对于服务器来说毫无意义，因为
	// 在这种情况下不支持重新协商。）
	secureRenegotiation bool
	// ekm是用于导出关键帧材质的闭包。
	ekm func(label string, context []byte, length int) ([]byte, error)
	// resumptionSecret是用于处理的恢复主密钥
	// 新闻票证信息。如果config.sessiontickets被禁用，则为nil。
	resumptionSecret []byte

	// ticketKeys是此会话的活动会话票证密钥集
	// 联系第一个用于加密新票据和
	// 所有人都试图解密门票。
	ticketKeys []ticketKey

	// 如果客户端发送了第一个已完成的
	// 在最近的握手过程中发送消息。这是因为
	// 第一条传输完成的消息是tls唯一消息
	// 通道绑定值。
	clientFinishedIsFirst bool

	// CloseNotifyError是发送alertCloseNotify记录时发生的任何错误。
	closeNotifyErr error
	// 如果Conn试图发送消息，则closeNotifySent为true
	// 警报关闭通知记录。
	closeNotifySent bool

	// clientFinished和serverFinished包含已发送的已完成消息
	// 由客户端或服务器在最近的握手中执行。这是
	// 保留以支持重新协商扩展和tls unique
	// 通道绑定。
	clientFinished [12]byte
	serverFinished [12]byte

	// clientProtocol是协商的ALPN协议。
	clientProtocol string

	// 输入/输出
	in, out   halfConn
	rawInput  bytes.Buffer // 原始输入，从记录头开始
	input     bytes.Reader // 等待从rawInput读取的应用程序数据。下一步
	hand      bytes.Buffer // 等待读取的握手数据
	buffering bool         // 是否在sendBuf中缓冲记录
	sendBuf   []byte       // 等待发送的记录的缓冲区

	// bytesSent统计发送的应用程序数据的字节数。
	// packetsSent统计数据包。
	bytesSent   int64
	packetsSent int64

	// retryCount统计连续非前进记录的数量
	// 由Conn.readRecord接收。也就是说，记录表明，这两种方法都没有推进
	// 握手，也不传递应用程序数据。受in.Mutex保护。
	retryCount int

	// activeCall是一个原子int32；低位是关闭是否已关闭
	// 有人打电话来。其余的位是goroutine的数量
	// 在康涅狄格州写。
	activeCall int32

	tmp [16]byte
}

// 访问net.Conn方法。
// 不能只嵌入net.Conn，因为那样会
// 也导出struct字段。

// LocalAddr返回本地网络地址。
func (c *Conn) LocalAddr() net.Addr {
	return c.conn.LocalAddr()
}

// RemoteAddr返回远程网络地址。
func (c *Conn) RemoteAddr() net.Addr {
	return c.conn.RemoteAddr()
}

// SetDeadline设置与连接关联的读写截止日期。
// t的零值表示读写不会超时。
// 写入超时后，TLS状态已损坏，将来的所有写入操作都将返回相同的错误。
func (c *Conn) SetDeadline(t time.Time) error {
	return c.conn.SetDeadline(t)
}

// SetReadDeadline设置基础连接的读取截止日期。
// t的零值表示读取不会超时。
func (c *Conn) SetReadDeadline(t time.Time) error {
	return c.conn.SetReadDeadline(t)
}

// SetWriteDeadline设置基础连接的写入截止日期。
// t的零值表示写入不会超时。
// 写入超时后，TLS状态已损坏，将来的所有写入操作都将返回相同的错误。
func (c *Conn) SetWriteDeadline(t time.Time) error {
	return c.conn.SetWriteDeadline(t)
}

// halfConn表示记录层的一个方向
// 连接，发送或接收。
type halfConn struct {
	sync.Mutex

	err     error       // 第一永久误差
	version uint16      // 协议版本
	cipher  interface{} // 密码算法
	mac     hash.Hash
	seq     [8]byte // 64位序列号

	scratchBuf [13]byte // 避免allocs；接口方法args escape

	nextCipher interface{} // 下一加密状态
	nextMac    hash.Hash   // 下一代MAC算法

	trafficSecret []byte // 当前TLS 1.3交通秘密
}

type permanentError struct {
	err net.Error
}

func (e *permanentError) Error() string   { return e.err.Error() }
func (e *permanentError) Unwrap() error   { return e.err }
func (e *permanentError) Timeout() bool   { return e.err.Timeout() }
func (e *permanentError) Temporary() bool { return false }

func (hc *halfConn) setErrorLocked(err error) error {
	if e, ok := err.(net.Error); ok {
		hc.err = &permanentError{err: e}
	} else {
		hc.err = err
	}
	return hc.err
}

// prepareCipherSpec设置加密和MAC状态
// 后续更改CipherSpec将使用的。
func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) {
	hc.version = version
	hc.nextCipher = cipher
	hc.nextMac = mac
}

// changeCipherSpec更改加密和MAC状态
// 之前传递给prepareCipherSpec的。
func (hc *halfConn) changeCipherSpec() error {
	if hc.nextCipher == nil || hc.version == VersionTLS13 {
		return alertInternalError
	}
	hc.cipher = hc.nextCipher
	hc.mac = hc.nextMac
	hc.nextCipher = nil
	hc.nextMac = nil
	for i := range hc.seq {
		hc.seq[i] = 0
	}
	return nil
}

func (hc *halfConn) setTrafficSecret(suite *cipherSuiteTLS13, secret []byte) {
	hc.trafficSecret = secret
	key, iv := suite.trafficKey(secret)
	hc.cipher = suite.aead(key, iv)
	for i := range hc.seq {
		hc.seq[i] = 0
	}
}

// incSeq递增序列号。
func (hc *halfConn) incSeq() {
	for i := 7; i >= 0; i-- {
		hc.seq[i]++
		if hc.seq[i] != 0 {
			return
		}
	}

	// 不允许让序列号换行。
	// 相反，我们必须在谈判之前进行重新谈判。
	// 可能还不够麻烦。
	panic("TLS: sequence number wraparound")
}

// explicitNonceLen返回包含的显式nonce或IV的字节数
// 在每个记录中。显式nonce仅在TLS 1.0之后的CBC模式中出现
// 以及TLS 1.2中的某些AEAD模式。
func (hc *halfConn) explicitNonceLen() int {
	if hc.cipher == nil {
		return 0
	}

	switch c := hc.cipher.(type) {
	case cipher.Stream:
		return 0
	case aead:
		return c.explicitNonceLen()
	case cbcMode:
		// TLS 1.1引入了每记录显式IV来修复BEAST攻击。
		if hc.version >= VersionTLS11 {
			return c.BlockSize()
		}
		return 0
	default:
		panic("unknown cipher type")
	}
}

// extractPadding以固定时间返回要删除的填充的长度
// 从有效载荷的末端开始。如果
// 填充有效，否则为0。见RFC 2246，第6.2.3.2节。
func extractPadding(payload []byte) (toRemove int, good byte) {
	if len(payload) < 1 {
		return 0, 0
	}

	paddingLen := payload[len(payload)-1]
	t := uint(len(payload)-1) - uint(paddingLen)
	// 如果len（有效载荷）>=（paddingLen-1），则t的MSB为零
	good = byte(int32(^t) >> 31)

	// 最大可能的填充长度加上实际长度字段
	toCheck := 256
	// 填充数据的长度是公共的，所以我们可以在这里使用if
	if toCheck > len(payload) {
		toCheck = len(payload)
	}

	for i := 0; i < toCheck; i++ {
		t := uint(paddingLen) - uint(i)
		// 如果i<=paddingLen，则t的MSB为零
		mask := byte(int32(^t) >> 31)
		b := payload[len(payload)-1-i]
		good &^= mask&paddingLen ^ mask&b
	}

	// 我们把好的东西放在一起，并在不同的领域复制结果
	// 所有的碎片。
	good &= good << 4
	good &= good << 2
	good &= good << 1
	good = uint8(int8(good) >> 7)

	// 错误时将填充长度归零。这可以确保任何未检查的字节
	// 都包含在MAC中。否则，攻击者可能会
	// 区分MAC故障和填充故障可能引发攻击
	// 与SSL 3.0中的POODLE类似：给定一个使用
	// 满块的填充值，用另一个块替换最后一个块
	// 块如果MAC检查通过，但填充检查失败，则
	// 该块的最后一个字节解密为块大小。
	// None
	// 另请参见下面的macAndPaddingGood逻辑。
	paddingLen &= good

	toRemove = int(paddingLen) + 1
	return
}

func roundUp(a, b int) int {
	return a + (b-a%b)%b
}

// cbcMode是使用密码块链接的分组密码接口。
type cbcMode interface {
	cipher.BlockMode
	SetIV([]byte)
}

// decrypt在保护处于活动状态时对记录进行身份验证和解密
// 这个阶段。返回的纯文本可能与输入重叠。
func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) {
	var plaintext []byte
	typ := recordType(record[0])
	payload := record[recordHeaderLen:]

	// 在TLS 1.3中，更改\u密码\u规范消息将被忽略，而不会被忽略
	// 解密。见RFC 8446，附录D.4。
	if hc.version == VersionTLS13 && typ == recordTypeChangeCipherSpec {
		return payload, typ, nil
	}

	paddingGood := byte(255)
	paddingLen := 0

	explicitNonceLen := hc.explicitNonceLen()

	if hc.cipher != nil {
		switch c := hc.cipher.(type) {
		case cipher.Stream:
			c.XORKeyStream(payload, payload)
		case aead:
			if len(payload) < explicitNonceLen {
				return nil, 0, alertBadRecordMAC
			}
			nonce := payload[:explicitNonceLen]
			if len(nonce) == 0 {
				nonce = hc.seq[:]
			}
			payload = payload[explicitNonceLen:]

			var additionalData []byte
			if hc.version == VersionTLS13 {
				additionalData = record[:recordHeaderLen]
			} else {
				additionalData = append(hc.scratchBuf[:0], hc.seq[:]...)
				additionalData = append(additionalData, record[:3]...)
				n := len(payload) - c.Overhead()
				additionalData = append(additionalData, byte(n>>8), byte(n))
			}

			var err error
			plaintext, err = c.Open(payload[:0], nonce, payload, additionalData)
			if err != nil {
				return nil, 0, alertBadRecordMAC
			}
		case cbcMode:
			blockSize := c.BlockSize()
			minPayload := explicitNonceLen + roundUp(hc.mac.Size()+1, blockSize)
			if len(payload)%blockSize != 0 || len(payload) < minPayload {
				return nil, 0, alertBadRecordMAC
			}

			if explicitNonceLen > 0 {
				c.SetIV(payload[:explicitNonceLen])
				payload = payload[explicitNonceLen:]
			}
			c.CryptBlocks(payload, payload)

			// 在一个有限的尝试，以防止CBC填充神谕，如
			// 幸运的是，经过paddingLen（这是秘密的）的数据被传递给了
			// MAC作为额外数据发挥作用，在传输后输入HMAC
			// 计算摘要。这使得MAC的时间大致保持不变
			// 只要摘要计算是恒定时间且不
			// None
			paddingLen, paddingGood = extractPadding(payload)
		default:
			panic("unknown cipher type")
		}

		if hc.version == VersionTLS13 {
			if typ != recordTypeApplicationData {
				return nil, 0, alertUnexpectedMessage
			}
			if len(plaintext) > maxPlaintext+1 {
				return nil, 0, alertRecordOverflow
			}
			// 删除填充并从末尾查找ContentType扫描。
			for i := len(plaintext) - 1; i >= 0; i-- {
				if plaintext[i] != 0 {
					typ = recordType(plaintext[i])
					plaintext = plaintext[:i]
					break
				}
				if i == 0 {
					return nil, 0, alertUnexpectedMessage
				}
			}
		}
	} else {
		plaintext = payload
	}

	if hc.mac != nil {
		macSize := hc.mac.Size()
		if len(payload) < macSize {
			return nil, 0, alertBadRecordMAC
		}

		n := len(payload) - macSize - paddingLen
		n = subtle.ConstantTimeSelect(int(uint32(n)>>31), 0, n) // 如果n<0{n=0}
		record[3] = byte(n >> 8)
		record[4] = byte(n)
		remoteMAC := payload[n : n+macSize]
		localMAC := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload[:n], payload[n+macSize:])

		// 这相当于检查Mac和paddingGood
		// 分开，但时间恒定，以防止区分
		// 从MAC故障中填充故障。取决于什么值
		// paddingLen的返回为错误填充，区分
		// 不良填充导致的不良MAC可能导致攻击。
		// None
		// 另请参见本文末尾的逻辑。
		macAndPaddingGood := subtle.ConstantTimeCompare(localMAC, remoteMAC) & int(paddingGood)
		if macAndPaddingGood != 1 {
			return nil, 0, alertBadRecordMAC
		}

		plaintext = payload[:n]
	}

	hc.incSeq()
	return plaintext, typ, nil
}

// sliceForAppend将输入片扩展n个字节。头部完全伸展
// 切片，而尾部是附加部分。如果原始切片具有足够的
// 不执行容量分配。
func sliceForAppend(in []byte, n int) (head, tail []byte) {
	if total := len(in) + n; cap(in) >= total {
		head = in[:total]
	} else {
		head = make([]byte, total)
		copy(head, in)
	}
	tail = head[len(in):]
	return
}

// encrypt加密有效负载，添加适当的nonce和/或MAC，以及
// 将其附加到记录，该记录必须已包含记录头。
func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, error) {
	if hc.cipher == nil {
		return append(record, payload...), nil
	}

	var explicitNonce []byte
	if explicitNonceLen := hc.explicitNonceLen(); explicitNonceLen > 0 {
		record, explicitNonce = sliceForAppend(record, explicitNonceLen)
		if _, isCBC := hc.cipher.(cbcMode); !isCBC && explicitNonceLen < 16 {
			// TLS中的AES-GCM构造具有明确的nonce，因此
			// nonce可以是随机的。但是，nonce只有8个字节，这是
			// 对于一个安全的、随机的nonce来说太小了。因此，我们使用
			// 序列号作为nonce。3DES-CBC结构也具有
			// 8字节的nonce，但其nonce必须是不可预测的（参见RFC
			// None
			// 3DES最大的问题是因为生日快到了
			// 碰撞首先到达，因为其块大小相似
			// （见32攻击）。
			copy(explicitNonce, hc.seq[:])
		} else {
			if _, err := io.ReadFull(rand, explicitNonce); err != nil {
				return nil, err
			}
		}
	}

	var dst []byte
	switch c := hc.cipher.(type) {
	case cipher.Stream:
		mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil)
		record, dst = sliceForAppend(record, len(payload)+len(mac))
		c.XORKeyStream(dst[:len(payload)], payload)
		c.XORKeyStream(dst[len(payload):], mac)
	case aead:
		nonce := explicitNonce
		if len(nonce) == 0 {
			nonce = hc.seq[:]
		}

		if hc.version == VersionTLS13 {
			record = append(record, payload...)

			// 加密实际的ContentType并替换明文类型。
			record = append(record, record[0])
			record[0] = byte(recordTypeApplicationData)

			n := len(payload) + 1 + c.Overhead()
			record[3] = byte(n >> 8)
			record[4] = byte(n)

			record = c.Seal(record[:recordHeaderLen],
				nonce, record[recordHeaderLen:], record[:recordHeaderLen])
		} else {
			additionalData := append(hc.scratchBuf[:0], hc.seq[:]...)
			additionalData = append(additionalData, record[:recordHeaderLen]...)
			record = c.Seal(record, nonce, payload, additionalData)
		}
	case cbcMode:
		mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil)
		blockSize := c.BlockSize()
		plaintextLen := len(payload) + len(mac)
		paddingLen := blockSize - plaintextLen%blockSize
		record, dst = sliceForAppend(record, plaintextLen+paddingLen)
		copy(dst, payload)
		copy(dst[len(payload):], mac)
		for i := plaintextLen; i < len(dst); i++ {
			dst[i] = byte(paddingLen - 1)
		}
		if len(explicitNonce) > 0 {
			c.SetIV(explicitNonce)
		}
		c.CryptBlocks(dst, dst)
	default:
		panic("unknown cipher type")
	}

	// 更新长度以包括nonce、MAC和所需的任何块填充。
	n := len(record) - recordHeaderLen
	record[3] = byte(n >> 8)
	record[4] = byte(n)
	hc.incSeq()

	return record, nil
}

// 当TLS记录头无效时，将返回RecordHeaderError。
type RecordHeaderError struct {
	// Msg包含描述错误的可读字符串。
	Msg string
	// RecordHeader包含TLS记录头的五个字节
	// 触发了错误。
	RecordHeader [5]byte
	// Conn在客户端
	// 发送了一个看起来不像TLS的初始握手。
	// 如果已经有握手或TLS警报，则为零
	// 已写入连接。
	Conn net.Conn
}

func (e RecordHeaderError) Error() string { return "tls: " + e.Msg }

func (c *Conn) newRecordHeaderError(conn net.Conn, msg string) (err RecordHeaderError) {
	err.Msg = msg
	err.Conn = conn
	copy(err.RecordHeader[:], c.rawInput.Bytes())
	return err
}

func (c *Conn) readRecord() error {
	return c.readRecordOrCCS(false)
}

func (c *Conn) readChangeCipherSpec() error {
	return c.readRecordOrCCS(true)
}

// readRecordOrCCS从连接读取一个或多个TLS记录，然后
// 更新记录层状态。一些不变量：
// *c.in必须上锁
// *c.输入必须为空
// 在握手过程中，会发生以下情况之一：
// -手长
// -c.in.changeCipherSpec被称为
// -返回一个错误
// 握手后，将发生且仅发生以下一种情况：
// -手长
// -c.设置输入
// -返回一个错误
func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error {
	if c.in.err != nil {
		return c.in.err
	}
	handshakeComplete := c.handshakeComplete()

	// 此函数修改c.rawInput，它拥有c.input内存。
	if c.input.Len() != 0 {
		return c.in.setErrorLocked(errors.New("tls: internal error: attempted to read record with pending application data"))
	}
	c.input.Reset(nil)

	// 读取标题，有效载荷。
	if err := c.readFromUntil(c.conn, recordHeaderLen); err != nil {
		// RFC 8446，第6.1节建议，无alertCloseNotify的EOF
		// 这是一个错误，但流行网站似乎做到了这一点，所以我们接受它
		// 当且仅当记录边界处。
		if err == io.ErrUnexpectedEOF && c.rawInput.Len() == 0 {
			err = io.EOF
		}
		if e, ok := err.(net.Error); !ok || !e.Temporary() {
			c.in.setErrorLocked(err)
		}
		return err
	}
	hdr := c.rawInput.Bytes()[:recordHeaderLen]
	typ := recordType(hdr[0])

	// 没有有效的TLS记录具有0x80类型，但是SSLv2握手
	// 从设置MSB的uint16长度和第一条记录开始
	// 长度始终小于256字节。因此，typ==0x80强烈建议
	// 一个SSLv2客户端。
	if !handshakeComplete && typ == 0x80 {
		c.sendAlert(alertProtocolVersion)
		return c.in.setErrorLocked(c.newRecordHeaderError(nil, "unsupported SSLv2 handshake received"))
	}

	vers := uint16(hdr[1])<<8 | uint16(hdr[2])
	n := int(hdr[3])<<8 | int(hdr[4])
	if c.haveVers && c.vers != VersionTLS13 && vers != c.vers {
		c.sendAlert(alertProtocolVersion)
		msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers)
		return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg))
	}
	if !c.haveVers {
		// 第一条信息，请格外怀疑：这可能不是TLS
		// 客户如果可能的话，在阅读完整的“正文”之前退出。
		// 当前最大版本为3.3，因此如果版本>=16.0，
		// 这可能不是真的。
		if (typ != recordTypeAlert && typ != recordTypeHandshake) || vers >= 0x1000 {
			return c.in.setErrorLocked(c.newRecordHeaderError(c.conn, "first record does not look like a TLS handshake"))
		}
	}
	if c.vers == VersionTLS13 && n > maxCiphertextTLS13 || n > maxCiphertext {
		c.sendAlert(alertRecordOverflow)
		msg := fmt.Sprintf("oversized record received with length %d", n)
		return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg))
	}
	if err := c.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
		if e, ok := err.(net.Error); !ok || !e.Temporary() {
			c.in.setErrorLocked(err)
		}
		return err
	}

	// 处理消息。
	record := c.rawInput.Next(recordHeaderLen + n)
	data, typ, err := c.in.decrypt(record)
	if err != nil {
		return c.in.setErrorLocked(c.sendAlert(err.(alert)))
	}
	if len(data) > maxPlaintext {
		return c.in.setErrorLocked(c.sendAlert(alertRecordOverflow))
	}

	// 应用程序数据消息始终受到保护。
	if c.in.cipher == nil && typ == recordTypeApplicationData {
		return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
	}

	if typ != recordTypeAlert && typ != recordTypeChangeCipherSpec && len(data) > 0 {
		// 这是一条状态推进消息：重置重试计数。
		c.retryCount = 0
	}

	// 握手消息不得与TLS 1.3中的其他记录类型交错。
	if c.vers == VersionTLS13 && typ != recordTypeHandshake && c.hand.Len() > 0 {
		return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
	}

	switch typ {
	default:
		return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))

	case recordTypeAlert:
		if len(data) != 2 {
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}
		if alert(data[1]) == alertCloseNotify {
			return c.in.setErrorLocked(io.EOF)
		}
		if c.vers == VersionTLS13 {
			return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
		}
		switch data[0] {
		case alertLevelWarning:
			// 将记录放到地板上，然后重试。
			return c.retryReadRecord(expectChangeCipherSpec)
		case alertLevelError:
			return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
		default:
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}

	case recordTypeChangeCipherSpec:
		if len(data) != 1 || data[0] != 1 {
			return c.in.setErrorLocked(c.sendAlert(alertDecodeError))
		}
		// 握手消息不允许在CCS中分割。
		if c.hand.Len() > 0 {
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}
		// 在TLS 1.3中，更改密码规格记录将被忽略，直到
		// 完成了。见RFC 8446，附录D.4。请注意，根据第节
		// 5、服务器可以在其ServerHello之前发送ChangeCipherSpec，当
		// c、 目前还没有定论。但这是没有用的，如果
		// 服务器然后选择较低的协议版本，所以不允许这样做。
		if c.vers == VersionTLS13 {
			return c.retryReadRecord(expectChangeCipherSpec)
		}
		if !expectChangeCipherSpec {
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}
		if err := c.in.changeCipherSpec(); err != nil {
			return c.in.setErrorLocked(c.sendAlert(err.(alert)))
		}

	case recordTypeApplicationData:
		if !handshakeComplete || expectChangeCipherSpec {
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}
		// 一些OpenSSL服务器发送空记录以随机化
		// CBC IV.忽略有限数量的空记录。
		if len(data) == 0 {
			return c.retryReadRecord(expectChangeCipherSpec)
		}
		// 注意，在上面的下一个调用之后，数据由c.rawInput拥有，
		// 避免复制纯文本。这是安全的，因为c.rawInput是
		// 在c.input耗尽之前不读取或写入。
		c.input.Reset(data)

	case recordTypeHandshake:
		if len(data) == 0 || expectChangeCipherSpec {
			return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}
		c.hand.Write(data)
	}

	return nil
}

// retryReadRecord递归到ReadRecordorCs以删除非前进记录，如
// TLS 1.3中的警告警报、空应用程序数据或更改密码规范。
func (c *Conn) retryReadRecord(expectChangeCipherSpec bool) error {
	c.retryCount++
	if c.retryCount > maxUselessRecords {
		c.sendAlert(alertUnexpectedMessage)
		return c.in.setErrorLocked(errors.New("tls: too many ignored records"))
	}
	return c.readRecordOrCCS(expectChangeCipherSpec)
}

// 至少读取N个字节后，atLeastReader将从R读取，并使用EOF停止
// 阅读它不同于io.LimitedReader，因为它不会缩短
// 最后一次读取调用，因为它认为早期EOF是一个错误。
type atLeastReader struct {
	R io.Reader
	N int64
}

func (r *atLeastReader) Read(p []byte) (int, error) {
	if r.N <= 0 {
		return 0, io.EOF
	}
	n, err := r.R.Read(p)
	r.N -= int64(n) // 除非len（p）>=n>9223372036854775809，否则不会下溢
	if r.N > 0 && err == io.EOF {
		return n, io.ErrUnexpectedEOF
	}
	if r.N <= 0 && err == nil {
		return n, io.EOF
	}
	return n, err
}

// readFromUntil从r读入c.rawInput，直到c.rawInput包含
// 至少n个字节，否则返回错误。
func (c *Conn) readFromUntil(r io.Reader, n int) error {
	if c.rawInput.Len() >= n {
		return nil
	}
	needs := n - c.rawInput.Len()
	// 线路上可能有额外的输入等待。尽力
	// 尝试获取它以便在（*Conn）中使用。读取到
	// “预测”关闭通知警报。
	c.rawInput.Grow(needs + bytes.MinRead)
	_, err := c.rawInput.ReadFrom(&atLeastReader{r, int64(needs)})
	return err
}

// sendAlert发送TLS警报消息。
func (c *Conn) sendAlertLocked(err alert) error {
	switch err {
	case alertNoRenegotiation, alertCloseNotify:
		c.tmp[0] = alertLevelWarning
	default:
		c.tmp[0] = alertLevelError
	}
	c.tmp[1] = byte(err)

	_, writeErr := c.writeRecordLocked(recordTypeAlert, c.tmp[0:2])
	if err == alertCloseNotify {
		// closeNotify是一种特殊情况，因为它不是错误。
		return writeErr
	}

	return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
}

// sendAlert发送TLS警报消息。
func (c *Conn) sendAlert(err alert) error {
	c.out.Lock()
	defer c.out.Unlock()
	return c.sendAlertLocked(err)
}

const (
	// tcpMSSEstimate是TCP最大段的保守估计
	// 尺寸（MSS）。使用常量，而不是查询内核中的
	// 实际的MSS，以避免复杂性。这里的值是IPv6
	// 最小MTU（1280字节）减去IPv6标头（40字节）的开销
	// 字节）和带有时间戳的TCP标头（32字节）。
	tcpMSSEstimate = 1208

	// RecordSizeBostThreshold是应用程序数据的字节数
	// 发送后，TLS记录大小将增加到
	// 最大限度
	recordSizeBoostThreshold = 128 * 1024
)

// maxPayloadSizeForWrite返回要用于
// 下一个应用程序数据记录。有以下权衡：
// None
// -对于延迟敏感的应用程序，如web浏览，每个TLS
// 记录应适合于一个TCP段。
// -对于吞吐量敏感的应用程序，如大型文件传输，
// 较大的TLS记录可以更好地分摊成帧和加密开销。
// None
// 一个在实践中效果很好的简单启发式方法是使用小记录
// 第一个1MB的数据，然后使用较大的记录作为后续数据，以及
// 连接空闲后，重置回较小的记录。见“高”
// 性能网络”，第4章，或：
// https:
// None
// 出于简单性和确定性的考虑，本代码不尝试
// 但是，在连接空闲时重置记录大小。
func (c *Conn) maxPayloadSizeForWrite(typ recordType) int {
	if c.config.DynamicRecordSizingDisabled || typ != recordTypeApplicationData {
		return maxPlaintext
	}

	if c.bytesSent >= recordSizeBoostThreshold {
		return maxPlaintext
	}

	// 减去TLS开销以获得最大有效负载大小。
	payloadBytes := tcpMSSEstimate - recordHeaderLen - c.out.explicitNonceLen()
	if c.out.cipher != nil {
		switch ciph := c.out.cipher.(type) {
		case cipher.Stream:
			payloadBytes -= c.out.mac.Size()
		case cipher.AEAD:
			payloadBytes -= ciph.Overhead()
		case cbcMode:
			blockSize := ciph.BlockSize()
			// 有效负载必须适合块大小的倍数，并且
			// 至少有一个填充字节的空间。
			payloadBytes = (payloadBytes & ^(blockSize - 1)) - 1
			// MAC在填充之前追加，因此会影响
			// 有效载荷大小直接决定。
			payloadBytes -= c.out.mac.Size()
		default:
			panic("unknown cipher type")
		}
	}
	if c.vers == VersionTLS13 {
		payloadBytes-- // 加密内容类型
	}

	// 允许数据包以算术级数增长到最大值。
	pkt := c.packetsSent
	c.packetsSent++
	if pkt > 1000 {
		return maxPlaintext // 在下面的乘法中避免溢出
	}

	n := payloadBytes * int(pkt+1)
	if n > maxPlaintext {
		n = maxPlaintext
	}
	return n
}

func (c *Conn) write(data []byte) (int, error) {
	if c.buffering {
		c.sendBuf = append(c.sendBuf, data...)
		return len(data), nil
	}

	n, err := c.conn.Write(data)
	c.bytesSent += int64(n)
	return n, err
}

func (c *Conn) flush() (int, error) {
	if len(c.sendBuf) == 0 {
		return 0, nil
	}

	n, err := c.conn.Write(c.sendBuf)
	c.bytesSent += int64(n)
	c.sendBuf = nil
	c.buffering = false
	return n, err
}

// ExputFPool池writeRecordLocked使用的记录大小的暂存缓冲区。
var outBufPool = sync.Pool{
	New: func() interface{} {
		return new([]byte)
	},
}

// writeRecordLocked将具有给定类型和负载的TLS记录写入
// 连接并更新记录层状态。
func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
	outBufPtr := outBufPool.Get().(*[]byte)
	outBuf := *outBufPtr
	defer func() {
		// 您可能想通过传递&exputf来简化这一点，
		// 但这会使EXBUF切片头的本地副本转义
		// 到堆，导致分配。取而代之的是，我们一直围绕着
		// 指向Get返回的切片标头的指针，该标头已位于
		// 堆，然后覆盖并返回。
		*outBufPtr = outBuf
		outBufPool.Put(outBufPtr)
	}()

	var n int
	for len(data) > 0 {
		m := len(data)
		if maxPayload := c.maxPayloadSizeForWrite(typ); m > maxPayload {
			m = maxPayload
		}

		_, outBuf = sliceForAppend(outBuf[:0], recordHeaderLen)
		outBuf[0] = byte(typ)
		vers := c.vers
		if vers == 0 {
			// 如果记录版本为，则某些TLS服务器会失败
			// 对于初始ClientHello，大于TLS 1.0。
			vers = VersionTLS10
		} else if vers == VersionTLS13 {
			// TLS1.3将记录层版本冻结为1.2。
			// 见RFC 8446，第5.1节。
			vers = VersionTLS12
		}
		outBuf[1] = byte(vers >> 8)
		outBuf[2] = byte(vers)
		outBuf[3] = byte(m >> 8)
		outBuf[4] = byte(m)

		var err error
		outBuf, err = c.out.encrypt(outBuf, data[:m], c.config.rand())
		if err != nil {
			return n, err
		}
		if _, err := c.write(outBuf); err != nil {
			return n, err
		}
		n += m
		data = data[m:]
	}

	if typ == recordTypeChangeCipherSpec && c.vers != VersionTLS13 {
		if err := c.out.changeCipherSpec(); err != nil {
			return n, c.sendAlertLocked(err.(alert))
		}
	}

	return n, nil
}

// writeRecord将具有给定类型和负载的TLS记录写入
// 连接并更新记录层状态。
func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) {
	c.out.Lock()
	defer c.out.Unlock()

	return c.writeRecordLocked(typ, data)
}

// readHandshake从中读取下一个握手消息
// 记录层。
func (c *Conn) readHandshake() (interface{}, error) {
	for c.hand.Len() < 4 {
		if err := c.readRecord(); err != nil {
			return nil, err
		}
	}

	data := c.hand.Bytes()
	n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
	if n > maxHandshake {
		c.sendAlertLocked(alertInternalError)
		return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake))
	}
	for c.hand.Len() < 4+n {
		if err := c.readRecord(); err != nil {
			return nil, err
		}
	}
	data = c.hand.Next(4 + n)
	var m handshakeMessage
	switch data[0] {
	case typeHelloRequest:
		m = new(helloRequestMsg)
	case typeClientHello:
		m = new(clientHelloMsg)
	case typeServerHello:
		m = new(serverHelloMsg)
	case typeNewSessionTicket:
		if c.vers == VersionTLS13 {
			m = new(newSessionTicketMsgTLS13)
		} else {
			m = new(newSessionTicketMsg)
		}
	case typeCertificate:
		if c.vers == VersionTLS13 {
			m = new(certificateMsgTLS13)
		} else {
			m = new(certificateMsg)
		}
	case typeCertificateRequest:
		if c.vers == VersionTLS13 {
			m = new(certificateRequestMsgTLS13)
		} else {
			m = &certificateRequestMsg{
				hasSignatureAlgorithm: c.vers >= VersionTLS12,
			}
		}
	case typeCertificateStatus:
		m = new(certificateStatusMsg)
	case typeServerKeyExchange:
		m = new(serverKeyExchangeMsg)
	case typeServerHelloDone:
		m = new(serverHelloDoneMsg)
	case typeClientKeyExchange:
		m = new(clientKeyExchangeMsg)
	case typeCertificateVerify:
		m = &certificateVerifyMsg{
			hasSignatureAlgorithm: c.vers >= VersionTLS12,
		}
	case typeFinished:
		m = new(finishedMsg)
	case typeEncryptedExtensions:
		m = new(encryptedExtensionsMsg)
	case typeEndOfEarlyData:
		m = new(endOfEarlyDataMsg)
	case typeKeyUpdate:
		m = new(keyUpdateMsg)
	default:
		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
	}

	// 握手消息解组器
	// 希望能够保留对数据的引用，
	// 因此，请传入一个不会被覆盖的新副本。
	data = append([]byte(nil), data...)

	if !m.unmarshal(data) {
		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
	}
	return m, nil
}

var (
	errShutdown = errors.New("tls: protocol is shutdown")
)

// 写入将数据写入连接。
// None
// As Write调用握手，以防止无限期阻塞截止日期
// 在握手时调用Write之前，必须为Read和Write设置
// 尚未完成。请参见设置截止日期、设置读取截止日期和
// SetWriteDeadline。
func (c *Conn) Write(b []byte) (int, error) {
	// 与下面的关闭联锁
	for {
		x := atomic.LoadInt32(&c.activeCall)
		if x&1 != 0 {
			return 0, net.ErrClosed
		}
		if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
			break
		}
	}
	defer atomic.AddInt32(&c.activeCall, -2)

	if err := c.Handshake(); err != nil {
		return 0, err
	}

	c.out.Lock()
	defer c.out.Unlock()

	if err := c.out.err; err != nil {
		return 0, err
	}

	if !c.handshakeComplete() {
		return 0, alertInternalError
	}

	if c.closeNotifySent {
		return 0, errShutdown
	}

	// TLS 1.0易受所选明文的影响
	// 使用块模式密码时由于可预测的IVs而受到攻击。
	// 这可以通过拆分每个应用程序数据来防止
	// 将记录分为两个记录，有效地随机化静脉注射。
	// None
	// https:
	// https:
	// https:

	var m int
	if len(b) > 1 && c.vers == VersionTLS10 {
		if _, ok := c.out.cipher.(cipher.BlockMode); ok {
			n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1])
			if err != nil {
				return n, c.out.setErrorLocked(err)
			}
			m, b = 1, b[1:]
		}
	}

	n, err := c.writeRecordLocked(recordTypeApplicationData, b)
	return n + m, c.out.setErrorLocked(err)
}

// HandlerEngotiation处理HelloRequest握手消息。
func (c *Conn) handleRenegotiation() error {
	if c.vers == VersionTLS13 {
		return errors.New("tls: internal error: unexpected renegotiation")
	}

	msg, err := c.readHandshake()
	if err != nil {
		return err
	}

	helloReq, ok := msg.(*helloRequestMsg)
	if !ok {
		c.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(helloReq, msg)
	}

	if !c.isClient {
		return c.sendAlert(alertNoRenegotiation)
	}

	switch c.config.Renegotiation {
	case RenegotiateNever:
		return c.sendAlert(alertNoRenegotiation)
	case RenegotiateOnceAsClient:
		if c.handshakes > 1 {
			return c.sendAlert(alertNoRenegotiation)
		}
	case RenegotiateFreelyAsClient:
		// 好啊
	default:
		c.sendAlert(alertInternalError)
		return errors.New("tls: unknown Renegotiation value")
	}

	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()

	atomic.StoreUint32(&c.handshakeStatus, 0)
	if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil {
		c.handshakes++
	}
	return c.handshakeErr
}

// handlePostHandshakeMessage处理在发送后到达的握手消息
// 握手完毕。在TLS 1.2之前，它表示重新谈判的开始。
func (c *Conn) handlePostHandshakeMessage() error {
	if c.vers != VersionTLS13 {
		return c.handleRenegotiation()
	}

	msg, err := c.readHandshake()
	if err != nil {
		return err
	}

	c.retryCount++
	if c.retryCount > maxUselessRecords {
		c.sendAlert(alertUnexpectedMessage)
		return c.in.setErrorLocked(errors.New("tls: too many non-advancing records"))
	}

	switch msg := msg.(type) {
	case *newSessionTicketMsgTLS13:
		return c.handleNewSessionTicket(msg)
	case *keyUpdateMsg:
		return c.handleKeyUpdate(msg)
	default:
		c.sendAlert(alertUnexpectedMessage)
		return fmt.Errorf("tls: received unexpected handshake message of type %T", msg)
	}
}

func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
	cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite)
	if cipherSuite == nil {
		return c.in.setErrorLocked(c.sendAlert(alertInternalError))
	}

	newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
	c.in.setTrafficSecret(cipherSuite, newSecret)

	if keyUpdate.updateRequested {
		c.out.Lock()
		defer c.out.Unlock()

		msg := &keyUpdateMsg{}
		_, err := c.writeRecordLocked(recordTypeHandshake, msg.marshal())
		if err != nil {
			// 在下一次写入时显示错误。
			c.out.setErrorLocked(err)
			return nil
		}

		newSecret := cipherSuite.nextTrafficSecret(c.out.trafficSecret)
		c.out.setTrafficSecret(cipherSuite, newSecret)
	}

	return nil
}

// 读取从连接中读取数据。
// None
// 因为读调用握手，以防止无限期阻塞截止日期
// 在握手时调用Read之前，必须为Read和Write设置
// 尚未完成。请参见设置截止日期、设置读取截止日期和
// SetWriteDeadline。
func (c *Conn) Read(b []byte) (int, error) {
	if err := c.Handshake(); err != nil {
		return 0, err
	}
	if len(b) == 0 {
		// 把这个放在握手之后，以防有人打电话
		// 阅读（无）了解握手的副作用。
		return 0, nil
	}

	c.in.Lock()
	defer c.in.Unlock()

	for c.input.Len() == 0 {
		if err := c.readRecord(); err != nil {
			return 0, err
		}
		for c.hand.Len() > 0 {
			if err := c.handlePostHandshakeMessage(); err != nil {
				return 0, err
			}
		}
	}

	n, _ := c.input.Read(b)

	// 如果正在等待close notify警报，请阅读该警报，以便我们可以返回（n，
	// EOF）而不是（n，nil），向HTTP响应读取发送信号
	// goroutine连接现在已关闭。这就消除了种族歧视
	// 否则，读取goroutine的HTTP响应将无法观察到
	// EOF直到下一次读取，此时客户端goroutine可能
	// 已尝试为新请求重用HTTP连接。
	// 请参阅https:
	if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 &&
		recordType(c.rawInput.Bytes()[0]) == recordTypeAlert {
		if err := c.readRecord(); err != nil {
			return n, err // 将在closeNotify上显示io.EOF
		}
	}

	return n, nil
}

// 关闭连接。
func (c *Conn) Close() error {
	// 与连接器联锁。写在上面。
	var x int32
	for {
		x = atomic.LoadInt32(&c.activeCall)
		if x&1 != 0 {
			return net.ErrClosed
		}
		if atomic.CompareAndSwapInt32(&c.activeCall, x, x|1) {
			break
		}
	}
	if x != 0 {
		// io.Writer和io.Closer不应同时使用。
		// 如果在写操作当前正在进行时调用Close，
		// 将其理解为这样一种迹象，即这种接近实际上是公正的
		// 用于中断写入和/或清理资源和
		// 避免发送可能会阻塞的alertCloseNotify
		// 等待握手EMUTEX或c.out互斥。
		return c.conn.Close()
	}

	var alertErr error
	if c.handshakeComplete() {
		if err := c.closeNotify(); err != nil {
			alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err)
		}
	}

	if err := c.conn.Close(); err != nil {
		return err
	}
	return alertErr
}

var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake complete")

// CloseWrite关闭连接的写入端。应该是
// 在握手完成后调用，并且不在上调用CloseWrite
// 底层连接。大多数呼叫者应该只使用Close。
func (c *Conn) CloseWrite() error {
	if !c.handshakeComplete() {
		return errEarlyCloseWrite
	}

	return c.closeNotify()
}

func (c *Conn) closeNotify() error {
	c.out.Lock()
	defer c.out.Unlock()

	if !c.closeNotifySent {
		// 设置写入截止日期以防止可能永远阻塞。
		c.SetWriteDeadline(time.Now().Add(time.Second * 5))
		c.closeNotifyErr = c.sendAlertLocked(alertCloseNotify)
		c.closeNotifySent = true
		// 任何后续写入都将失败。
		c.SetWriteDeadline(time.Now())
	}
	return c.closeNotifyErr
}

// 握手运行客户端或服务器握手
// 协议（如果尚未运行）。
// None
// 这个包的大多数用法都不需要显式地调用握手：
// 第一次读或写将自动调用它。
// None
// 要控制取消或设置握手超时，请使用
// HandshakeContext或拨号程序的DialContext方法。
func (c *Conn) Handshake() error {
	return c.HandshakeContext(context.Background())
}

// HandshakeContext运行客户端或服务器握手
// 协议（如果尚未运行）。
// None
// 提供的上下文必须是非nil。如果之前取消了上下文
// 握手完成，握手被中断并返回错误。
// 握手完成后，取消上下文不会影响握手
// 联系
// None
// 这个包的大多数用法不需要显式调用HandshakeContext:
// 第一次读或写将自动调用它。
func (c *Conn) HandshakeContext(ctx context.Context) error {
	// 委托给命名返回的未报告方法
	// 没有混乱的文件签名。
	return c.handshakeContext(ctx)
}

func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
	handshakeCtx, cancel := context.WithCancel(ctx)
	// 注意：在启动“interrupter”goroutine之前推迟此操作
	// 这样我们就可以区分被取消的输入和
	// 这次取消。在前一种情况下，我们需要关闭连接。
	defer cancel()

	// 如果此上下文可能被取消，请启动“interrupter”goroutine。
	// （背景上下文无法显示）。
	// None
	// 中断程序goroutine等待完成输入上下文，然后
	// 如果在函数返回之前发生这种情况，则关闭连接。
	if ctx.Done() != nil {
		done := make(chan struct{})
		interruptRes := make(chan error, 1)
		defer func() {
			close(done)
			if ctxErr := <-interruptRes; ctxErr != nil {
				// 将上下文错误返回给用户。
				ret = ctxErr
			}
		}()
		go func() {
			select {
			case <-handshakeCtx.Done():
				// 关闭连接，放弃错误
				_ = c.conn.Close()
				interruptRes <- handshakeCtx.Err()
			case <-done:
				interruptRes <- nil
			}
		}()
	}

	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()

	if err := c.handshakeErr; err != nil {
		return err
	}
	if c.handshakeComplete() {
		return nil
	}

	c.in.Lock()
	defer c.in.Unlock()

	c.handshakeErr = c.handshakeFn(handshakeCtx)
	if c.handshakeErr == nil {
		c.handshakes++
	} else {
		// 如果在握手过程中发生错误，请尝试刷新
		// 可能留在缓冲区中的警报。
		c.flush()
	}

	if c.handshakeErr == nil && !c.handshakeComplete() {
		c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
	}

	return c.handshakeErr
}

// ConnectionState返回有关连接的基本TLS详细信息。
func (c *Conn) ConnectionState() ConnectionState {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	return c.connectionStateLocked()
}

func (c *Conn) connectionStateLocked() ConnectionState {
	var state ConnectionState
	state.HandshakeComplete = c.handshakeComplete()
	state.Version = c.vers
	state.NegotiatedProtocol = c.clientProtocol
	state.DidResume = c.didResume
	state.NegotiatedProtocolIsMutual = true
	state.ServerName = c.serverName
	state.CipherSuite = c.cipherSuite
	state.PeerCertificates = c.peerCertificates
	state.VerifiedChains = c.verifiedChains
	state.SignedCertificateTimestamps = c.scts
	state.OCSPResponse = c.ocspResponse
	if !c.didResume && c.vers != VersionTLS13 {
		if c.clientFinishedIsFirst {
			state.TLSUnique = c.clientFinished[:]
		} else {
			state.TLSUnique = c.serverFinished[:]
		}
	}
	if c.config.Renegotiation != RenegotiateNever {
		state.ekm = noExportedKeyingMaterial
	} else {
		state.ekm = c.ekm
	}
	return state
}

// OCSPResponse从TLS服务器返回装订好的OCSP响应（如果需要）
// 任何（仅对客户端连接有效。）
func (c *Conn) OCSPResponse() []byte {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()

	return c.ocspResponse
}

// VerifyHostname检查对等证书链是否对有效
// 正在连接到主机。若有，则返回零；如果不是，则返回一个错误
// 描述问题。
func (c *Conn) VerifyHostname(host string) error {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	if !c.isClient {
		return errors.New("tls: VerifyHostname called on TLS server connection")
	}
	if !c.handshakeComplete() {
		return errors.New("tls: handshake has not yet been performed")
	}
	if len(c.verifiedChains) == 0 {
		return errors.New("tls: handshake did not verify certificate chain")
	}
	return c.peerCertificates[0].VerifyHostname(host)
}

func (c *Conn) handshakeComplete() bool {
	return atomic.LoadUint32(&c.handshakeStatus) == 1
}
